import 'dart:io';
import 'dart:math';
import 'package:calendar_date_picker2/calendar_date_picker2.dart';
import 'package:flustars/flustars.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart';
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_nb_net/flutter_net.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:map_launcher/map_launcher.dart';
import 'package:tracker/common/constants/app_constants.dart';
import 'package:tracker/common/log/x_logger.dart';
import 'package:tracker/common/permission/permission_manager.dart';
import 'package:tracker/pages/home/location/model/monitor_data_resp.dart';
import 'package:tracker/pages/home/track/mixin/track_page_mixin.dart';
import 'package:tracker/pages/home/track/model/track_resp.dart';
import 'package:tracker/provider/global_provider.dart';
import 'package:tracker/router/router_manager.dart';
import 'package:tracker/theme/app_theme.dart';
import 'package:tracker/utils/location_utils.dart';
import 'package:tracker/utils/toast_utils.dart';
import 'package:shared_preferences/shared_preferences.dart';

const trackBeginIcon = 'assets/images/map/track_begin1.png';
const trackEndIcon = 'assets/images/map/track_end1.png';

/// 轨迹 页面
class TrackPage extends ConsumerStatefulWidget {
  const TrackPage({super.key});

  @override
  ConsumerState<TrackPage> createState() => _TrackPageState();
}

class _TrackPageState extends ConsumerState<TrackPage> with TrackPageMixin {
  BMFMapOptions mapOptions = BMFMapOptions(
      center: BMFCoordinate(39.917215, 116.380341),
      zoomLevel: 18,
      mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0));
  bool _mapisshow = true;

  BMFMapController? myMapController;
  BMFMarker? deviceMarker;
  BMFMarker? startMarker;
  BMFMarker? finishMarker;
  BMFTraceOverlay? _traceOverlay;
  BMFPolyline? _polyline;

  var playState = false;
  var isFirstStartThread = true;
  var isMoving = true;
  TrackData? mLastLatLng;
  TrackData? lastStartPoint;
  int moveIndex = 0;
  late double slope;
  late bool isYReverse;
  late bool isXReverse;
  late double intercept;
  late double xMoveDistance;
  late double yMoveDistance;
  late double mDistance = 0.00030;

  /// 轨迹播放的定时器，单位毫秒
  int mSleepTime = 60;
  bool canContinue = true;

  MonitorData? monitorData;

  bool showChooseTimeButton = false;
  bool showTimePanel = true;
  bool showPlayPanel = false;

  /// 是否显示日期选择工具栏
  bool showDateToolBar = false;
  int segCurrent = 0;

  // 开始时间，默认今天0点.结束时间，默认今天23:59:59
  DateTime startTime =
      DateTime.now().copyWith(hour: 0, minute: 0, second: 0, millisecond: 0);
  DateTime endTime = DateTime.now()
      .copyWith(hour: 23, minute: 59, second: 59, millisecond: 999);

  // DateTime startTime = DateTime.now().copyWith(hour: 0, minute: 0, second: 0, millisecond: 0, year: 2023, month: 12, day: 1);
  // DateTime endTime = DateTime.now().copyWith(hour: 13, minute: 59, second: 59, millisecond: 999, year: 2023, month: 12, day: 1);

  // 定位类型
  bool gpsChecked = true;
  bool wifiChecked = false;
  bool lbsChecked = false;

  List<TrackData> _trackDataList = [];
  List<TrackData> _calcCoordinateList = [];
  List<BMFMarker> _holdPointMarkerList = [];

  TimerUtil? timerUtil;

  /// 是否正在播放状态
  bool isPlaying = false;
  int playTrackDataIndex = 0;

  onBMFMapCreated(BMFMapController controller) {
    myMapController = controller;
    myMapController?.setMapDidLoadCallback(callback: () {
      XLogger.debug('地图加载完成');
    });
    myMapController?.updateMapOptions(BMFMapOptions(
      logoPosition: BMFLogoPosition.LeftTop,
      showZoomControl: false,
    ));
    myMapController?.setMapOnClickedMapPoiCallback(callback: (mapPoi) {
      XLogger.debug('点击了地图');
      // setState(() {
      //   showTimePanel = false;
      //   showChooseTimeButton = true;
      // });
    });
    myMapController?.setMapOnClickedMapBlankCallback(callback: (coordinate) {
      XLogger.debug('点击了地图空白处');
      // setState(() {
      //   showTimePanel = false;
      // });
    });
    // 处理marker点击事件
    myMapController!.setMapClickedMarkerCallback(callback: (marker) async {
      XLogger.debug(
          '点击了marker: ${marker.id}, identifier: ${marker.identifier}');
      // 傻逼百度获取不到设置的identifier，只能根据id来查找判断点击的是哪个marker
      // 真是日了狗了
      var markerWhere =
          _holdPointMarkerList.where((element) => element.id == marker.id);
      XLogger.debug('markerWhere: ${markerWhere.length}');
      if (markerWhere.isNotEmpty) {
        var holdPointMarker = markerWhere.first;
        var gpsDataId = holdPointMarker.identifier!.split('_')[1];
        var trackData = _trackDataList
            .firstWhere((element) => element.gpsDataId == gpsDataId);
        if (trackData != null) {
          // 停留时长(秒)，换算成多少时多少分钟，并格式化成整数
          var residenceTime = formatStayTime(trackData.residenceTime ?? 0);
          // 解析地址
          if (trackData.locationDesc == null ||
              trackData.locationDesc!.isEmpty) {
            ToastUtils.showLoading();
            trackData.locationDesc = await reverseGeoCode(trackData);
            ToastUtils.dismissLoading();
          }
          _showPointInfoDialog(residenceTime, trackData);
        }
      } else {
        // 点击了起点或终点
        XLogger.debug(
            '起点id: ${_trackDataList.first.gpsDataId}, 终点id: ${_trackDataList.last.gpsDataId}');
        if (marker.icon == trackBeginIcon) {
          _showStartEndPointInfoDialog(_trackDataList.first);
        } else if (marker.icon == trackEndIcon) {
          _showStartEndPointInfoDialog(_trackDataList.last, isStart: false);
        }
      }
    });
    _fetchDeviceLocation();
  }

  /// 显示起始点信息
  void _showStartEndPointInfoDialog(TrackData trackData,
      {bool isStart = true}) {
    var title = isStart ? '起点信息' : '终点信息';
    showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            contentPadding: const EdgeInsets.only(
              left: 20.0,
              top: 20.0,
              right: 20.0,
            ),
            actionsPadding:
                const EdgeInsets.only(left: 20.0, right: 20.0, bottom: 0),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      title,
                      style: const TextStyle(fontSize: 18),
                    ),
                    // 关闭按钮
                    GestureDetector(
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                      child: const Icon(
                        Icons.close,
                        size: 24,
                      ),
                    ),
                  ],
                ),
                const SizedBox(
                  height: 8,
                ),
                Row(
                  children: [
                    const Text('时间：'),
                    Text('${trackData.locationTime ?? ''}'),
                  ],
                ),
                Container(
                  alignment: Alignment.centerLeft,
                  child: Text(
                    '地址：${trackData.locationDesc ?? ''}',
                    maxLines: 3,
                    overflow: TextOverflow.ellipsis,
                    textAlign: TextAlign.left,
                  ),
                ),
              ],
            ),
            actions: [
              // 按钮：导航到该位置
              TextButton(
                child: const Text('导航到该位置'),
                onPressed: () {
                  context.pop();
                  _navToLocation(trackData);
                },
              ),
              TextButton(
                child: const Text('关闭'),
                onPressed: () {
                  context.pop();
                },
              ),
            ],
          );
        });
  }

  /// 显示停留点信息
  void _showPointInfoDialog(residenceTime, TrackData trackData) {
    showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            contentPadding: const EdgeInsets.only(
              left: 20.0,
              top: 20.0,
              right: 20.0,
            ),
            actionsPadding:
                const EdgeInsets.only(left: 20.0, right: 20.0, bottom: 0),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    const Text(
                      '停留点信息',
                      style: TextStyle(fontSize: 18),
                    ),
                    // 关闭按钮
                    GestureDetector(
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                      child: const Icon(
                        Icons.close,
                        size: 24,
                      ),
                    ),
                  ],
                ),
                const SizedBox(
                  height: 8,
                ),
                Row(
                  children: [
                    const Text('停留时长：'),
                    Text('${residenceTime}'),
                  ],
                ),
                Row(
                  children: [
                    const Text('开始时间：'),
                    Text('${trackData.residenceStartTime ?? ''}'),
                  ],
                ),
                Row(
                  children: [
                    const Text('结束时间：'),
                    Text('${trackData.residenceEndTime ?? ''}'),
                  ],
                ),
                Container(
                  alignment: Alignment.centerLeft,
                  child: Text(
                    '地址：${trackData.locationDesc ?? ''}',
                    maxLines: 3,
                    overflow: TextOverflow.ellipsis,
                    textAlign: TextAlign.left,
                  ),
                ),
              ],
            ),
            actions: [
              // 按钮：导航到该位置
              TextButton(
                child: const Text('导航到该位置'),
                onPressed: () {
                  context.pop();
                  _navToLocation(trackData);
                },
              ),
              TextButton(
                child: const Text('关闭'),
                onPressed: () {
                  context.pop();
                },
              ),
            ],
          );
        });
  }

  /// 点击按钮：导航到该位置
  _navToLocation(TrackData trackData) async {
    final availableMaps = await MapLauncher.installedMaps;
    XLogger.info(availableMaps);
    if (availableMaps.isNotEmpty) {
      // 显示bottomSheet
      _showMapSheet(availableMaps,
          latitude: trackData.latitude,
          longitude: trackData.longitude,
          title: trackData.locationDesc);
    } else {
      ToastUtils.showToast('没有安装地图软件');
    }
  }

  // todo: 2024-01-10 封装地图选择组件
  /// 显示地图选择
  _showMapSheet(List<AvailableMap> availableMaps,
      {double? latitude, double? longitude, String? title}) {
    final mapTitleMap = {
      'amap': '高德地图',
      'baidu': '百度地图',
      'google': '谷歌地图',
      'apple': '苹果地图',
      'google': '谷歌地图',
      'tencent': '腾讯地图',
    };
    showModalBottomSheet(
      context: context,
      builder: (BuildContext context) {
        return SizedBox(
          height: availableMaps.length * 60,
          child: ListView.builder(
            itemCount: availableMaps.length,
            itemBuilder: (BuildContext context, int index) {
              final map = availableMaps[index];
              final mapName =
                  mapTitleMap[map.mapType.name.toLowerCase()] ?? map.mapName;
              return ListTile(
                onTap: () {
                  map.showDirections(
                      destination: Coords(latitude ?? 0, longitude ?? 0),
                      destinationTitle: title ?? '');
                  Navigator.pop(context);
                },
                title: Text(mapName),
              );
            },
          ),
        );
      },
    );
  }

  Future<void> _fetchDeviceLocation() async {
    final deviceInfo = ref.watch(deviceInfoProvider);
    final resp = await getDeviceMonitor(deviceInfo.imei!);
    if (resp.code == 200 && resp.data?.latitude != null) {
      setState(() {
        monitorData = resp.data;
      });
      myMapController?.setCenterCoordinate(
          BMFCoordinate(resp.data!.latitude!, resp.data!.longitude!), true);
      if (deviceMarker == null) {
        deviceMarker = BMFMarker.icon(
          position: BMFCoordinate(resp.data!.latitude!, resp.data!.longitude!),
          icon: getDeviceMarkerIcon(),
          identifier: 'deviceMarker',
        );
        myMapController?.addMarker(deviceMarker!);
      } else {
        deviceMarker?.updatePosition(
            BMFCoordinate(resp.data!.latitude!, resp.data!.longitude!));
        deviceMarker?.updateIcon(getDeviceMarkerIcon());
      }
    }
  }

  Widget _buildSegmentButton(String text) {
    return Container(
      width: 100,
      alignment: Alignment.center,
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Text(text),
    );
  }

  Widget _buildSearchPanel() {
    return Column(
      children: [
        Text('选择时间',
            style: TextStyle(
              fontSize: 17,
              color: AppTheme.themeConfig.primaryTextColor,
            )),
        const SizedBox(
          height: 12,
        ),
        // 分段选择器，分为3个：今天，昨天，自定义
        CupertinoSegmentedControl(
          children: {
            0: _buildSegmentButton('今天'),
            1: _buildSegmentButton('昨天'),
            2: _buildSegmentButton('自定义'),
          },
          selectedColor: AppTheme.themeConfig.primaryColor,
          borderColor: AppTheme.themeConfig.primaryColor,
          groupValue: segCurrent,
          onValueChanged: (value) {
            if (value == 0 || value == 2) {
              startTime = DateTime.now()
                  .copyWith(hour: 0, minute: 0, second: 0, millisecond: 0);
              endTime = DateTime.now()
                  .copyWith(hour: 23, minute: 59, second: 59, millisecond: 999);
            } else if (value == 1) {
              startTime = DateTime.now()
                  .copyWith(hour: 0, minute: 0, second: 0, millisecond: 0)
                  .subtract(const Duration(days: 1));
              endTime = DateTime.now()
                  .copyWith(hour: 23, minute: 59, second: 59, millisecond: 999)
                  .subtract(const Duration(days: 1));
            }
            setState(() {
              segCurrent = value;
            });
          },
        ),
        const SizedBox(
          height: 12,
        ),
        Divider(
          height: 1,
          color: AppTheme.themeConfig.dividerColor,
        ),
        const SizedBox(
          height: 12,
        ),
        // 开始时间
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 12),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                '开始时间',
                style: TextStyle(
                  fontSize: 15,
                  color: AppTheme.themeConfig.primaryTextColor,
                ),
              ),
              GestureDetector(
                onTap: () {
                  if (segCurrent != 2) {
                    return;
                  }
                  _showStartTimePicker();
                },
                child: Text(
                  '${DateUtil.formatDate(startTime, format: 'yyyy-MM-dd')}',
                  style: TextStyle(
                    fontSize: 15,
                    color: AppTheme.themeConfig.primaryTextColor,
                  ),
                ),
              ),
            ],
          ),
        ),
        const SizedBox(
          height: 12,
        ),
        Divider(
          height: 1,
          color: AppTheme.themeConfig.dividerColor,
        ),
        const SizedBox(
          height: 12,
        ),
        // 结束时间
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 12),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                '结束时间',
                style: TextStyle(
                  fontSize: 15,
                  color: AppTheme.themeConfig.primaryTextColor,
                ),
              ),
              GestureDetector(
                onTap: () {
                  if (segCurrent != 2) {
                    return;
                  }
                  _showEndTimePicker();
                },
                child: Text(
                  '${DateUtil.formatDate(endTime, format: 'yyyy-MM-dd')}',
                  style: TextStyle(
                    fontSize: 15,
                    color: AppTheme.themeConfig.primaryTextColor,
                  ),
                ),
              ),
            ],
          ),
        ),
        const SizedBox(
          height: 12,
        ),
        Divider(
          height: 1,
          color: AppTheme.themeConfig.dividerColor,
        ),
        const SizedBox(
          height: 12,
        ),
        Row(
          children: [
            // 3个多选框，分别为：GPS，WIFI，基站定位
            Expanded(
              child: Row(
                children: [
                  Checkbox(
                    value: wifiChecked,
                    onChanged: (value) {
                      setState(() {
                        wifiChecked = value!;
                      });
                    },
                    activeColor: AppTheme.themeConfig.primaryColor,
                  ),
                  Text(
                    'WIFI',
                    style: TextStyle(
                      fontSize: 15,
                      color: AppTheme.themeConfig.primaryTextColor,
                    ),
                  ),
                ],
              ),
            ),
            Expanded(
              child: Row(
                children: [
                  Checkbox(
                    value: lbsChecked,
                    onChanged: (value) {
                      setState(() {
                        lbsChecked = value!;
                      });
                    },
                    activeColor: AppTheme.themeConfig.primaryColor,
                  ),
                  Text(
                    '基站定位',
                    style: TextStyle(
                      fontSize: 15,
                      color: AppTheme.themeConfig.primaryTextColor,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
        Row(
          children: [
            Expanded(
              flex: 2,
              child: TextButton(
                onPressed: () {
                  _fetchTrackData();
                },
                style: TextButton.styleFrom(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20),
                  ),
                  backgroundColor: AppTheme.themeConfig.primaryColor,
                ),
                child: const Text(
                  '开始回放',
                  style: TextStyle(
                    fontSize: 15,
                    color: Colors.white,
                  ),
                ),
              ),
            )
          ],
        )
      ],
    );
  }

  /// 播放控制面板
  Widget _buildPlayPanel() {
    const fontSize = 15.0;
    final fontColor = AppTheme.themeConfig.primaryTextColor;
    const labelWidth = 80.0;
    final deviceInfo = ref.watch(deviceInfoProvider);
    final playTrackData = _trackDataList[playTrackDataIndex];
    final longitude = playTrackData.longitude?.toStringAsFixed(6) ?? '';
    final latitude = playTrackData.latitude?.toStringAsFixed(6) ?? '';
    return Column(
      children: [
        Row(
          children: [
            Container(
              width: labelWidth,
              child: Text(
                '设备名称：',
                style: TextStyle(
                  fontSize: fontSize,
                  color: fontColor,
                ),
              ),
            ),
            Text(
              '${deviceInfo?.deviceName ?? ''}',
              style: TextStyle(
                fontSize: fontSize,
                color: fontColor,
              ),
            ),
          ],
        ),
        Row(
          children: [
            Container(
              width: labelWidth,
              child: Text(
                '设备号：',
                style: TextStyle(
                  fontSize: fontSize,
                  color: fontColor,
                ),
              ),
            ),
            Text(
              '${deviceInfo?.imei ?? ''}',
              style: TextStyle(
                fontSize: fontSize,
                color: fontColor,
              ),
            ),
          ],
        ),
        Row(
          children: [
            Container(
              width: labelWidth,
              child: Text(
                '定位时间：',
                style: TextStyle(
                  fontSize: fontSize,
                  color: fontColor,
                ),
              ),
            ),
            Text(
              '${playTrackData?.locationTime ?? ''}',
              style: TextStyle(
                fontSize: fontSize,
                color: fontColor,
              ),
            ),
          ],
        ),
        Row(
          children: [
            Container(
              width: labelWidth,
              child: Text(
                '定位类型：',
                style: TextStyle(
                  fontSize: fontSize,
                  color: fontColor,
                ),
              ),
            ),
            SizedBox(
              width: 90,
              child: Text(
                LocationUtils.getLocationTypeText(playTrackData.locationType),
                style: TextStyle(
                  fontSize: fontSize,
                  color: fontColor,
                ),
              ),
            ),
            const SizedBox(
              width: 12,
            ),
            Expanded(
              child: Row(
                children: [
                  Container(
                    width: labelWidth - 33,
                    child: Text(
                      '速度：',
                      style: TextStyle(
                        fontSize: fontSize,
                        color: fontColor,
                      ),
                    ),
                  ),
                  Text(
                    '${playTrackData.speed ?? ''}km/h',
                    style: TextStyle(
                      fontSize: fontSize,
                      color: fontColor,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
        Row(
          children: [
            Row(
              children: [
                Container(
                  width: labelWidth,
                  child: Text(
                    '经度：',
                    style: TextStyle(
                      fontSize: fontSize,
                      color: fontColor,
                    ),
                  ),
                ),
                SizedBox(
                  width: 90,
                  child: Text(
                    '${longitude}',
                    style: TextStyle(
                      fontSize: fontSize,
                      color: fontColor,
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(
              width: 12,
            ),
            Expanded(
              child: Row(
                children: [
                  Container(
                    width: labelWidth - 35,
                    child: Text(
                      '纬度:',
                      style: TextStyle(
                        fontSize: fontSize,
                        color: fontColor,
                      ),
                    ),
                  ),
                  Text(
                    '${latitude}',
                    style: TextStyle(
                      fontSize: fontSize,
                      color: fontColor,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  width: labelWidth,
                  child: Text(
                    '地址：',
                    style: TextStyle(
                      fontSize: fontSize,
                      color: fontColor,
                    ),
                  ),
                ),
              ],
            ),
            _buildPlayPanelLocationDescView(fontSize, fontColor),
          ],
        ),
        const SizedBox(
          height: 4,
        ),
        Divider(
          height: 1,
          color: AppTheme.themeConfig.dividerColor,
        ),
        const SizedBox(
          height: 4,
        ),
        SizedBox(
          height: 34,
          child: Row(
            children: [
              // 播放按钮，是一个图片按钮
              GestureDetector(
                onTap: () {
                  _startPlay();
                },
                child: Image.asset(
                  isPlaying
                      ? 'assets/images/map/pause.png'
                      : 'assets/images/map/play.png',
                  width: 26,
                  height: 26,
                ),
              ),
              // 进度条
              Expanded(
                child: Slider(
                  value: playPointIndex.toDouble(),
                  min: 0,
                  max: _calcCoordinateList.isNotEmpty
                      ? _calcCoordinateList.length.toDouble() - 1
                      : 0,
                  onChanged: (value) {
                    if (value.toInt() >= _calcCoordinateList.length) {
                      return;
                    }
                    setState(() {
                      playPointIndex = value.toInt();
                      _playing(playPointIndex);
                    });
                  },
                  onChangeEnd: (value) {
                    if (value.toInt() >= _calcCoordinateList.length) {
                      return;
                    }
                    // 拖动结束后，查询当前点的地址信息
                    _loadLocationDesc();
                  },
                ),
              ),
            ],
          ),
        )
      ],
    );
  }

  /// 播放面板中的地址信息
  Widget _buildPlayPanelLocationDescView(double fontSize, Color fontColor,
      {double labelWidth = 80.0}) {
    final playTrackData = _trackDataList[playTrackDataIndex];
    if (playTrackData.locationDesc == null ||
        playTrackData.locationDesc!.isEmpty) {
      return GestureDetector(
        onTap: () async {
          // 播放中，暂停查看详细地址
          if (isPlaying) {
            isPlaying = false;
            setState(() {});
            timerUtil?.cancel();
          }
          _loadLocationDesc();
        },
        child: Text(
          '暂停查看详细地址',
          style: TextStyle(
            fontSize: fontSize,
            color: AppTheme.themeConfig.primaryColor,
          ),
        ),
      );
    } else {
      return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
        Container(
          width: MediaQuery.of(context).size.width - (40 + labelWidth + 24),
          child: Text(
            '${playTrackData.locationDesc ?? ''}',
            style: TextStyle(
              fontSize: fontSize,
              color: fontColor,
            ),
            maxLines: 3,
            overflow: TextOverflow.ellipsis,
            softWrap: true,
          ),
        ),
      ]);
    }
  }

  /// 查询轨迹数据
  _fetchTrackData() async {
    // 定位类型
    List<String> locationTypes = [];
    if (gpsChecked) {
      locationTypes.add('1');
    }
    if (wifiChecked) {
      locationTypes.add('2');
    }
    if (lbsChecked) {
      locationTypes.add('3');
    }
    if (locationTypes.isEmpty) {
      ToastUtils.showToast('请选择定位类型');
      return;
    }
    // 开始时间不能大于结束时间
    if (startTime.isAfter(endTime)) {
      ToastUtils.showToast('开始时间不能大于结束时间');
      return;
    }
    // 开始时间和结束时间不能超过7天
    if (endTime.difference(startTime).inDays > 7) {
      ToastUtils.showToast('查询日期范围不能超过7天');
      return;
    }
    // 判断是否超出用户轨迹存储最小日期
    if (startTime.isBefore(userMinDate)) {
      XLogger.info('查询范围超出时长，请您购买轨迹存储服务，若您已购买请返回主页下拉刷新数据。');
      // ToastUtils.showToast('查询范围超出时长，请您购买轨迹存储服务，若您已购买请返回主页下拉刷新数据。');
      // 跳到【增值服务-轨迹存储】页面
      Future.delayed(const Duration(milliseconds: 500), () {
        ToastUtils.showSimpleDialog(
          context,
          title: '提示',
          content: '查询范围超出时长，请您购买轨迹存储服务，若您已购买请返回主页下拉刷新数据。',
          confirmTitle: '查看详情',
          cancelTitle: '返回主页',
          showCancel: true,
          confirmCallback: () {
            // 先返回主页，再跳转到增值服务-轨迹存储页面
            context.pop();
            context
                .push('${RouterManager.valueAddedService}?type=trackStorage');
          },
          cancelCallback: () {
            context.pop();
          },
        );
      });
      return;
    }
    // 只能查询最近180天的轨迹
    if (startTime
        .isBefore(DateTime.now().subtract(Duration(days: trackStorageDays)))) {
      ToastUtils.showToast('只能查询最近180天的轨迹');
      return;
    }
    final postData = {
      'imei': ref.read(deviceInfoProvider).imei,
      // 'imei': '58051025721',
      'beginTime':
          DateUtil.formatDate(startTime, format: 'yyyy-MM-dd HH:mm:ss'),
      'endTime': DateUtil.formatDate(endTime, format: 'yyyy-MM-dd HH:mm:ss'),
      'locationTypes': locationTypes,
    };
    if (_traceOverlay != null) {
      await myMapController!.removeTraceOverlay(_traceOverlay!.id);
      _traceOverlay = null;
    }
    ToastUtils.showLoading(maskType: EasyLoadingMaskType.clear);
    final res = await post<TrackResp, TrackResp>('/track/track',
        data: postData, decodeType: TrackResp());
    res.when(success: (resp) async {
      ToastUtils.dismissLoading();

      if (resp.code == 200) {
        if (resp.data != null && resp.data!.isNotEmpty) {
          _trackDataList = resp.data!;
          await _initTrackInfo(resp.data!);
          // 查询起点和终点的地址
          if (_trackDataList.isNotEmpty) {
            var firstTrackData = _trackDataList.first;
            if (firstTrackData.locationDesc == null ||
                firstTrackData.locationDesc!.isEmpty) {
              firstTrackData.locationDesc =
                  await reverseGeoCode(firstTrackData);
            }
            var lastTrackData = _trackDataList.last;
            if (lastTrackData.locationDesc == null ||
                lastTrackData.locationDesc!.isEmpty) {
              lastTrackData.locationDesc = await reverseGeoCode(lastTrackData);
            }
            setState(() {});
          }
        } else {
          ToastUtils.showToast(resp.msg ?? '暂无轨迹数据');
        }
      } else {
        _clearPolyline();
        ToastUtils.showToast(resp.msg ?? '暂无轨迹数据');
      }
      return null;
    }, failure: (String msg, int code) {
      XLogger.error('获取轨迹数据失败：msg: $msg, code: $code');
    });
  }

  _showStartTimePicker() async {
    if (!isRefreshTrackCalendar) {
      await loadTrackCalendarData();
    }
    var config = CalendarDatePicker2WithActionButtonsConfig(
      // 不能选择今天之后的日期
      lastDate: DateTime.now(),
      // 只能选择最近3个月的日期
      firstDate: DateTime.now().subtract(Duration(days: trackStorageDays)),
      dayBuilder: _dayBuilder,
    );
    var dialog = Dialog(
      insetPadding:
          const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
      backgroundColor: Theme.of(context).canvasColor,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
      ),
      clipBehavior: Clip.antiAlias,
      child: SizedBox(
        width: 325,
        height: max(400, 410),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CalendarDatePicker2WithActionButtons(
              value: startTimeValue,
              config: config.copyWith(openedFromDialog: true),
              onValueChanged: (value) {
                setState(() {
                  startTimeValue = value;
                });
              },
              onOkTapped: () {
                if (startTimeValue.isNotEmpty) {
                  startTime = startTimeValue[0]!
                      .copyWith(hour: 0, minute: 0, second: 0, millisecond: 0);
                }
              },
            ),
          ],
        ),
      ),
    );
    showDialog(context: context, builder: (context) => dialog);
  }

  _showEndTimePicker() async {
    if (!isRefreshTrackCalendar) {
      await loadTrackCalendarData();
    }
    var config = CalendarDatePicker2WithActionButtonsConfig(
      // 不能选择今天之后的日期
      lastDate: DateTime.now(),
      // 只能选择最近3个月的日期
      firstDate: DateTime.now().subtract(Duration(days: trackStorageDays)),
      dayBuilder: _dayBuilder,
    );
    var dialog = Dialog(
      insetPadding:
          const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0),
      backgroundColor: Theme.of(context).canvasColor,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
      ),
      clipBehavior: Clip.antiAlias,
      child: SizedBox(
        width: 325,
        height: max(400, 410),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CalendarDatePicker2WithActionButtons(
              value: endTimeValue,
              config: config.copyWith(openedFromDialog: true),
              onValueChanged: (value) {
                setState(() {
                  endTimeValue = value;
                });
              },
              onOkTapped: () {
                if (endTimeValue.isNotEmpty) {
                  endTime = endTimeValue[0]!
                      .copyWith(hour: 0, minute: 0, second: 0, millisecond: 0);
                }
              },
            ),
          ],
        ),
      ),
    );
    showDialog(context: context, builder: (context) => dialog);
  }

  Widget _buildChooseTimeButton() {
    return TextButton(
        onPressed: () {
          setState(() {
            showTimePanel = true;
            showChooseTimeButton = false;
            showPlayPanel = false;
          });
        },
        child: Text(
          '选择时间',
          style: TextStyle(
              color: AppTheme.themeConfig.primaryTextColor, fontSize: 17),
        ));
  }

  /// 构建顶部日期工具栏
  Widget _buildDateToolTopView() {
    return Positioned(
      top: 30,
      left: 20,
      right: 20,
      child: Container(
        width: double.infinity,
        height: 45,
        color: Color(0xFFFFFFFF),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            // 前一天
            GestureDetector(
              onTap: () {},
              child: Text("< 前一天"),
            ),
            // 点击时间
            GestureDetector(
              onTap: () async {
                if (!isRefreshTrackCalendar) {
                  await loadTrackCalendarData();
                }
                var config = CalendarDatePicker2WithActionButtonsConfig(
                  // 不能选择今天之后的日期
                  lastDate: DateTime.now(),
                  // 只能选择最近3个月的日期
                  firstDate:
                      DateTime.now().subtract(Duration(days: trackStorageDays)),
                  dayBuilder: _dayBuilder,
                );
                var dialog = Dialog(
                  insetPadding: const EdgeInsets.symmetric(
                      horizontal: 16.0, vertical: 24.0),
                  backgroundColor: Theme.of(context).canvasColor,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                  clipBehavior: Clip.antiAlias,
                  child: SizedBox(
                    width: 325,
                    height: max(400, 410),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        CalendarDatePicker2WithActionButtons(
                          value: calendarValue,
                          config: config.copyWith(openedFromDialog: true),
                          onValueChanged: (value) {
                            setState(() {
                              calendarValue = value;
                            });
                          },
                          onOkTapped: () {
                            if (calendarValue.isNotEmpty) {
                              startTime = calendarValue[0]!.copyWith(
                                  hour: 0,
                                  minute: 0,
                                  second: 0,
                                  millisecond: 0);
                              endTime = calendarValue[0]!.copyWith(
                                  hour: 23,
                                  minute: 59,
                                  second: 59,
                                  millisecond: 999);
                              _fetchTrackData();
                            }
                          },
                        ),
                      ],
                    ),
                  ),
                );
                showDialog(context: context, builder: (context) => dialog);
              },
              child: Row(
                children: [
                  Image(
                    width: 20,
                    image: AssetImage('assets/images/home/date_blue.png'),
                    fit: BoxFit.fitWidth,
                  ),
                  SizedBox(
                    width: 4,
                  ),
                  Text(
                      '${DateUtil.formatDate(startTime, format: 'yyyy-MM-dd')}'),
                ],
              ),
            ),
            GestureDetector(
              onTap: () {},
              child: Text("后一天 >"),
            ),
          ],
        ),
      ),
    );
  }

  /// 构建顶部日期工具栏弹框
  Widget _buildDateToolView() {
    if (!showDateToolBar) {
      return Container();
    }
    return Positioned(
      left: 20,
      right: 20,
      top: 20,
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 8),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(12),
        ),
        height: 50,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            GestureDetector(
              onTap: () {
                // 如果正在播放轨迹，就暂停
                showPlayPanel = false;
                playTrackDataIndex = 0;
                isPlaying = false;
                timerUtil?.cancel();
                setState(() {});
                // 查询前一天的数据
                startTime = startTime.subtract(const Duration(days: 1));
                endTime = startTime.copyWith(
                    hour: 23, minute: 59, second: 59, millisecond: 999);
                _fetchTrackData();
              },
              child: Row(
                children: [
                  Icon(
                    Icons.arrow_back_ios,
                    size: 20,
                    color: AppTheme.themeConfig.primaryTextColor,
                  ),
                  Text(
                    '前一天',
                    style: TextStyle(
                        color: AppTheme.themeConfig.primaryTextColor,
                        fontSize: 17),
                  ),
                ],
              ),
            ),
            GestureDetector(
              onTap: () {
                // 如果正在播放轨迹，就暂停
                playTrackDataIndex = 0;
                isPlaying = false;
                timerUtil?.cancel();

                showTimePanel = true;
                showChooseTimeButton = false;
                showPlayPanel = false;
                setState(() {});
              },
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    '选择 ${DateUtil.formatDate(startTime, format: 'yyyy-MM-dd')}',
                    style: TextStyle(color: AppTheme.themeConfig.primaryColor),
                  ),
                  Text(
                    '日期 ${DateUtil.formatDate(endTime, format: 'yyyy-MM-dd')}',
                    style: TextStyle(color: AppTheme.themeConfig.primaryColor),
                  ),
                ],
              ),
            ),
            GestureDetector(
              onTap: () {
                // 如果endTime是今天，就不能再后一天了
                if (endTime.isAfter(DateTime.now()
                    .copyWith(hour: 0, minute: 0, second: 0, millisecond: 0))) {
                  ToastUtils.showToast('不能查询未来的轨迹');
                  return;
                }
                playTrackDataIndex = 0;
                isPlaying = false;
                timerUtil?.cancel();
                showPlayPanel = false;

                setState(() {});
                // 查询后一天的数据
                startTime = startTime.add(const Duration(days: 1));
                endTime = startTime.copyWith(
                    hour: 23, minute: 59, second: 59, millisecond: 999);
                _fetchTrackData();
              },
              child: Row(
                children: [
                  Text(
                    '后一天',
                    style: TextStyle(
                        color: AppTheme.themeConfig.primaryTextColor,
                        fontSize: 17),
                  ),
                  Icon(
                    Icons.arrow_forward_ios,
                    size: 20,
                    color: AppTheme.themeConfig.primaryTextColor,
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }

  Widget _buildBottomView() {
    return Positioned(
      left: 20,
      right: 20,
      bottom: 20,
      child: Container(
        width: double.infinity,
        // height: 120,
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(12),
        ),
        child: _showView(),
      ),
    );
  }

  Widget _showView() {
    if (showChooseTimeButton) {
      return _buildChooseTimeButton();
    } else if (showTimePanel) {
      return _buildSearchPanel();
    } else if (showPlayPanel) {
      return _buildPlayPanel();
    } else {
      return Container();
    }
  }

  /// 初始化轨迹信息
  Future<void> _initTrackInfo(List<TrackData> trackDataList) async {
    setState(() {
      showTimePanel = false;
      showChooseTimeButton = false;
      showPlayPanel = true;
      showDateToolBar = true;
    });
    // 绘制轨迹
    _clearPolyline();
    _drawPolyline();

    if (startMarker != null) {
      myMapController?.removeMarker(startMarker!);
      startMarker = null;
    }
    startMarker = BMFMarker.icon(
      position: BMFCoordinate(
          trackDataList[0].latitude!, trackDataList[0].longitude!),
      icon: trackBeginIcon,
      identifier: 'startMarker',
    );
    myMapController?.addMarker(startMarker!);
    if (finishMarker != null) {
      myMapController?.removeMarker(finishMarker!);
      finishMarker = null;
    }
    finishMarker = BMFMarker.icon(
      position: BMFCoordinate(trackDataList[trackDataList.length - 1].latitude!,
          trackDataList[trackDataList.length - 1].longitude!),
      icon: trackEndIcon,
      identifier: 'finishMarker',
    );
    myMapController?.addMarker(finishMarker!);

    if (deviceMarker != null) {
      myMapController?.removeMarker(deviceMarker!);
      deviceMarker = null;
    }

    // myMapController!.setZoomTo(18);
    // myMapController!.setCenterCoordinate(startCoor, true);
    isMoving = true;
    playState = false;
    _calcCoordinateList = [];
    moveIndex = 0;
    playPointIndex = 0;
    _moveLopper();
    XLogger.info('_trackDataList: ${_trackDataList.length}');
    XLogger.info('_calcCoordinateList: ${_calcCoordinateList.length}');

    // 删除所有停留点标记
    if (_holdPointMarkerList.isNotEmpty) {
      myMapController?.removeMarkers(_holdPointMarkerList);
      _holdPointMarkerList.clear();
    }
    // 绘制所有停留点标记
    // 查询所有停留点
    var stayPoints = _calcCoordinateList
        .where((element) => element.holdPoint != null && element.holdPoint!)
        .toList();
    XLogger.info('stayPoints: ${stayPoints.length}');
    for (var i = 0; i < _calcCoordinateList.length; i++) {
      var calcTrackData = _calcCoordinateList[i];
      if (calcTrackData.holdPoint != null && calcTrackData.holdPoint!) {
        _addHoldPointMarker(i);
      }
    }
  }

  /// 解析地址
  _loadLocationDesc() async {
    // 暂定时解析当前点的地址
    var playTrackData = _trackDataList[playTrackDataIndex];
    if (playTrackData.locationDesc == null ||
        playTrackData.locationDesc!.isEmpty) {
      playTrackData.locationDesc = await reverseGeoCode(playTrackData);
    }
    setState(() {});
  }

  /// 开始播放
  _startPlay() async {
    if (isPlaying) {
      // 暂停
      isPlaying = false;
      setState(() {});
      timerUtil?.cancel();
      _loadLocationDesc();
      return;
    }
    // 如果当前下标是最后一个，就从头开始播放
    if (playPointIndex >= _calcCoordinateList.length - 1) {
      playPointIndex = 0;
    }

    isPlaying = true;
    setState(() {});
    // 开一个定时器播放
    if (timerUtil != null) {
      timerUtil!.startTimer();
    } else {
      timerUtil = TimerUtil();
      timerUtil!.setInterval(mSleepTime);
      timerUtil!.setOnTimerTickCallback((millisUntilFinished) {
        // XLogger.debug('playPointIndex: $playPointIndex');
        if (playPointIndex >= _calcCoordinateList.length - 1) {
          ToastUtils.showSimpleDialog(
            context,
            title: '提示',
            content: '轨迹回放结束',
          );
          isPlaying = false;
          setState(() {});
          timerUtil!.cancel();
          return;
        }
        _playing(playPointIndex);
        playPointIndex++;
      });
      timerUtil!.startTimer();
    }
  }

  /// 移动marker
  _playing(int index) {
    _addDeviceMarker();
    final point = _calcCoordinateList[index];
    BMFCoordinate coordinate = BMFCoordinate(point.latitude!, point.longitude!);
    deviceMarker?.updatePosition(coordinate);
    // 判断是否在可视区域内
    // 判断是否停留点
    // if (point.holdPoint != null && point.holdPoint!) {
    //   XLogger.info('停留点坐标：${point.longitude}, ${point.latitude}, id: ${point.gpsDataId}');
    //   _addHoldPointMarker(index);
    // }
    // 判断当前点在_trackDataList中的下标，主要用于显示当前点的信息，当前点的信息是从_trackDataList中获取的，根据playTrackDataIndex
    var trackDataIndex = _trackDataList
        .indexWhere((element) => element.gpsDataId == point.gpsDataId);
    if (trackDataIndex != -1) {
      playTrackDataIndex = trackDataIndex;
    }
    setState(() {});
  }

  _addDeviceMarker() {
    if (deviceMarker == null) {
      var startCoor = BMFCoordinate(
          _trackDataList[0].latitude!, _trackDataList[0].longitude!);
      deviceMarker = BMFMarker.icon(
        position: startCoor,
        icon: 'assets/images/map/track_icon.png',
        identifier: 'deviceMarker',
        // centerOffset: BMFPoint(0, -20)
      );
      myMapController?.addMarker(deviceMarker!);
    }
  }

  /// 添加停留点标记物
  _addHoldPointMarker(int index) {
    final point = _calcCoordinateList[index];
    if (point.gpsDataId == null) {
      return;
    }
    XLogger.info('add marker：${point.gpsDataId}');
    var holdPointMarker = BMFMarker.icon(
      position: BMFCoordinate(point.latitude!, point.longitude!),
      icon: 'assets/images/map/track_stop1.png',
      identifier: 'holdPointMarker_${point.gpsDataId!}',
    );
    myMapController!.addMarker(holdPointMarker);
    _holdPointMarkerList.add(holdPointMarker);
  }

  _clearPolyline() {
    if (_polyline != null) {
      myMapController?.removeOverlay(_polyline!.id);
      _polyline = null;
    }
  }

  /// 画轨迹
  _drawPolyline() async {
    List<BMFCoordinate> coords = [];
    for (var trackData in _trackDataList) {
      BMFCoordinate coordinate =
          BMFCoordinate(trackData.latitude!, trackData.longitude!);
      coords.add(coordinate);
    }
    if (_polyline != null) {
      _polyline!.updateCoordinates(coords);
      myMapController!.setVisibleMapRectWithPadding(
        visibleMapBounds: getVisibleMapRect(coords),
        insets: const EdgeInsets.symmetric(horizontal: 30, vertical: 30),
        animated: true,
      );
      return;
    }

    /// 创建polyline
    _polyline = BMFPolyline(
        coordinates: coords,
        colors: [Colors.blue],
        width: Platform.isIOS ? 6 : 16,
        dottedLine: false,
        lineCapType: BMFLineCapType.LineCapButt,
        lineJoinType: BMFLineJoinType.LineJoinRound);

    /// 添加polyline
    myMapController?.addPolyline(_polyline!);
    myMapController!.setVisibleMapRectWithPadding(
      visibleMapBounds: getVisibleMapRect(coords),
      insets: const EdgeInsets.symmetric(horizontal: 30, vertical: 30),
      animated: true,
    );
  }

  /// 获取地图显示区域
  BMFCoordinateBounds getVisibleMapRect(List<BMFCoordinate> coordinates) {
    BMFCoordinate fisrt = coordinates[0];
    double leftBottomX = fisrt.latitude;
    double leftBottomY = fisrt.longitude;
    double rightTopX = fisrt.latitude;
    double rightTopY = fisrt.longitude;

    for (BMFCoordinate coordinate in coordinates) {
      if (coordinate.latitude < leftBottomX) {
        leftBottomX = coordinate.latitude;
      }

      if (coordinate.longitude < leftBottomY) {
        leftBottomY = coordinate.longitude;
      }

      if (coordinate.latitude > rightTopX) {
        rightTopX = coordinate.latitude;
      }

      if (coordinate.longitude > rightTopY) {
        rightTopY = coordinate.longitude;
      }
    }

    BMFCoordinate leftBottom = BMFCoordinate(leftBottomX, leftBottomY);
    BMFCoordinate rightTop = BMFCoordinate(rightTopX, rightTopY);

    BMFCoordinateBounds coordinateBounds =
        BMFCoordinateBounds(northeast: rightTop, southwest: leftBottom);

    return coordinateBounds;
  }

  /// 计算轨迹点
  void _moveLopper() {
    for (int i = 0; i < _trackDataList.length - 2;) {
      if (isMoving) {
        // XLogger.debug('moveIndex: $moveIndex');
        int i = moveIndex;
        var startPoint = _trackDataList[i];
        var endPoint = _trackDataList[i + 1];
        if (mLastLatLng != null && lastStartPoint != null) {
          if (startPoint.latitude == lastStartPoint!.latitude &&
              startPoint.longitude == lastStartPoint!.longitude) {
            _moveMarker(mLastLatLng!, endPoint, false);
          } else {
            _moveMarker(startPoint, endPoint, true);
          }
        } else {
          _moveMarker(startPoint, endPoint, true);
        }
        lastStartPoint = startPoint;
        moveIndex++;
        if (i == _trackDataList.length - 2) {
          isMoving = false;
          playState = true;
          XLogger.info('播放结束');
          return;
          // ToastUtils.showToast('播放结束');
        }
      }
    }
  }

  void _moveMarker(
      TrackData startTrackData, TrackData endTrackData, bool right) {
    if (startTrackData.holdPoint != null && startTrackData.holdPoint!) {
      // 如果是停留点，就不移动
      XLogger.info(
          '停留点坐标：${startTrackData.longitude}, ${startTrackData.latitude}, id: ${startTrackData.gpsDataId}');
    }
    var startPoint =
        BMFCoordinate(startTrackData.latitude!, startTrackData.longitude!);
    var endPoint =
        BMFCoordinate(endTrackData.latitude!, endTrackData.longitude!);
    if (isMoving) {
      if (right) {
        // deviceMarker!.updatePosition(startPoint);
        // myMapController!.setCenterCoordinate(startPoint, true);
        _calcCoordinateList.add(startTrackData);

        slope = _getSlope(startPoint, endPoint);
        isYReverse = (startPoint.latitude > endPoint.latitude);
        isXReverse = (startPoint.longitude > endPoint.longitude);
        intercept = _getInterception(slope, startPoint);
        xMoveDistance = isXReverse
            ? _getXMoveDistance(slope)
            : -1 * _getXMoveDistance(slope);
        yMoveDistance = isYReverse
            ? _getYMoveDistance(slope)
            : -1 * _getYMoveDistance(slope);
      }

      for (double j = startPoint.latitude, k = startPoint.longitude;
          !((j > endPoint.latitude) ^ isYReverse) &&
              !((k > endPoint.longitude) ^ isXReverse);) {
        if (!isMoving) {
          moveIndex--;
          break;
        }
        BMFCoordinate latLng;
        if (slope == double.infinity) {
          latLng = BMFCoordinate(j, k);
          j = j - yMoveDistance;
        } else if (slope == 0.0) {
          latLng = BMFCoordinate(j, k - xMoveDistance);
          k = k - xMoveDistance;
        } else {
          latLng = BMFCoordinate(j, (j - intercept) / slope);
          j = j - yMoveDistance;
        }
        BMFCoordinate finalLatLng = latLng;
        mLastLatLng = startTrackData.copyWith(
            latitude: latLng.latitude,
            longitude: latLng.longitude,
            holdPoint: false);
        if (finalLatLng.latitude == 0 && finalLatLng.longitude == 0) {
          continue;
        }
        // deviceMarker!.updatePosition(finalLatLng);
        if (endPoint.longitude == finalLatLng.longitude &&
            endPoint.latitude == finalLatLng.latitude) {
          _calcCoordinateList.add(endTrackData);
        } else {
          var finalTrackData = startTrackData.copyWith(
              latitude: finalLatLng.latitude,
              longitude: finalLatLng.longitude,
              holdPoint: false,
              gpsDataId: startTrackData.gpsDataId);
          _calcCoordinateList.add(finalTrackData);
        }
      }
    }
  }

  double _getXMoveDistance(double slope) {
    if (slope == double.infinity || slope == 0.0) {
      return mDistance;
    }
    return (mDistance * 1 / slope) / sqrt(1 + 1 / (slope * slope)).abs();
  }

  double _getYMoveDistance(double slope) {
    if (slope == double.infinity || slope == 0.0) {
      return mDistance;
    }
    return ((mDistance * slope) / sqrt(1 + slope * slope)).abs();
  }

  /// 算斜率
  double _getSlope(BMFCoordinate fromPoint, BMFCoordinate toPoint) {
    if (toPoint.longitude == fromPoint.longitude) {
      return double.infinity;
    }
    double slope = ((toPoint.latitude - fromPoint.latitude) /
        (toPoint.longitude - fromPoint.longitude));
    return slope;
  }

  double _getInterception(double slope, BMFCoordinate point) {
    double interception = point.latitude - slope * point.longitude;
    return interception;
  }

  int playPointIndex = 0;
  var fromPause = false;

  Widget? _dayBuilder({
    required date,
    textStyle,
    decoration,
    isSelected,
    isDisabled,
    isToday,
  }) {
    Widget? dayWidget;

    // 今日之后、180天前的日历不处理
    if (date.isBefore(
            DateTime.now().subtract(Duration(days: trackStorageDays + 1))) ||
        date.isAfter(DateTime.now())) {
      return dayWidget;
    }
    // 如果小于用户最小日期，则将文字颜色设置为灰色
    if (date.isBefore(userMinDate)) {
      textStyle = textStyle.copyWith(color: AppTheme.themeConfig.infoTextColor);
    } else {
      textStyle =
          textStyle.copyWith(color: AppTheme.themeConfig.primaryTextColor);
    }
    // 只处理trackCalendar中的日期
    if (trackCalendar.isEmpty || !trackCalendar.contains(date)) {
      dayWidget = Container(
        decoration: decoration,
        alignment: Alignment.center,
        child: Text(
          MaterialLocalizations.of(context).formatDecimal(date.day),
          style: textStyle,
        ),
      );
      return dayWidget;
    }
    dayWidget = Container(
      decoration: decoration,
      alignment: Alignment.center,
      child: Center(
        child: Stack(
          alignment: AlignmentDirectional.center,
          children: [
            Text(
              MaterialLocalizations.of(context).formatDecimal(date.day),
              style: textStyle,
            ),
            Padding(
              padding: const EdgeInsets.only(top: 27.5),
              child: Container(
                height: 4,
                width: 4,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(5),
                  color: isSelected == true ? Colors.white : Colors.red[500],
                ),
              ),
            ),
          ],
        ),
      ),
    );

    return dayWidget;
  }

  /// 根据增值服务获取最小日期
  _getUserMinDate() {
    var deviceInfo = ref.watch(deviceInfoProvider);
    int trackStorageDays = deviceInfo.trackStorageDays ?? 7;
    return DateTime.now().subtract(Duration(days: trackStorageDays));
  }

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      // 获取设备定位
      _fetchDeviceLocation();
      // 根据增值服务获取最小日期
      userMinDate = _getUserMinDate();
      setState(() {});
    });
    super.initState();
    mapshow();

    PermissionManager.requestLocationPermissions(context);
  }
  Future<void> mapshow() async {

    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _mapisshow =  prefs.getBool("mapshow") ?? true;
      XLogger.info(_mapisshow);
    });

  }
  @override
  void dispose() {
    super.dispose();
    if (timerUtil != null) {
      timerUtil!.cancel();
      timerUtil = null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(kAppbarHeight),
        child: AppBar(
          leading: GestureDetector(
            onTap: () {
              Navigator.pop(context);
            },
            child: Container(
              height: kToolbarHeight,
              padding: const EdgeInsets.only(top: 8),
              alignment: Alignment.center,
              child: const Text(' <返回',
                  textAlign: TextAlign.center,
                  maxLines: 1,
                  style: TextStyle(color: Colors.black)),
            ),
          ),
          title: const Text(
            '动态轨迹',
          ),
          centerTitle: true,
          backgroundColor: AppTheme.themeConfig.navBarColor,
          foregroundColor: Colors.white,
          // 右上角日历按钮
          actions: [
            IconButton(
              onPressed: () async {
                if (!isRefreshTrackCalendar) {
                  await loadTrackCalendarData();
                }
                var config = CalendarDatePicker2WithActionButtonsConfig(
                  // 不能选择今天之后的日期
                  lastDate: DateTime.now(),
                  // 只能选择最近3个月的日期
                  firstDate:
                      DateTime.now().subtract(Duration(days: trackStorageDays)),
                  dayBuilder: _dayBuilder,
                );
                var dialog = Dialog(
                  insetPadding: const EdgeInsets.symmetric(
                      horizontal: 16.0, vertical: 24.0),
                  backgroundColor: Theme.of(context).canvasColor,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                  clipBehavior: Clip.antiAlias,
                  child: SizedBox(
                    width: 325,
                    height: max(400, 410),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        CalendarDatePicker2WithActionButtons(
                          value: calendarValue,
                          config: config.copyWith(openedFromDialog: true),
                          onValueChanged: (value) {
                            setState(() {
                              calendarValue = value;
                            });
                          },
                          onOkTapped: () {
                            if (calendarValue.isNotEmpty) {
                              startTime = calendarValue[0]!.copyWith(
                                  hour: 0,
                                  minute: 0,
                                  second: 0,
                                  millisecond: 0);
                              endTime = calendarValue[0]!.copyWith(
                                  hour: 23,
                                  minute: 59,
                                  second: 59,
                                  millisecond: 999);
                              _fetchTrackData();
                            }
                          },
                        ),
                      ],
                    ),
                  ),
                );
                showDialog(context: context, builder: (context) => dialog);
              },
              icon: const Icon(Icons.calendar_month_outlined),
            ),
          ],
        ),
      ),
      body: Stack(
        children: [
          if (_mapisshow)
            BMFMapWidget(
            onBMFMapCreated: (controller) {
              onBMFMapCreated(controller);
            },
            mapOptions: mapOptions,
          ),
          _buildDateToolTopView(),
          _buildDateToolView(),
          _buildBottomView(),
        ],
      ),
    );
  }
}
